<template>
  <el-tabs v-model="activeTab" :="attrs" @edit="handleEdit" @tabChange="tabChange">
    <el-tab-pane
      v-for="item in tabList"
      :key="item.name"
      :closable="item.closable"
      :label="item.label"
      :name="item.name"
      lazy
    >
      <component v-if="item.component" :is="item.component"></component>
    </el-tab-pane>
  </el-tabs>
</template>

<script setup>
import { ElMessageBox } from 'element-plus';
const tabList = defineModel('tabList');
const attrs = useAttrs();
const { activeTabKey } = defineProps({
  // 兼容一个页面存在多个标签页组件时，设置当前标签页组件切换时保留在路由上的key
  // 默认为tab，可自定义
  activeTabKey: {
    type: String,
    default: 'tab',
  },
});
const emit = defineEmits(['handleEdit']);
const router = useRouter();
const route = useRoute();
const activeTab = computed({
  get: () => {
    return route.query[activeTabKey] || tabList.value[0].name;
  },
  set: (newVal) => {
    return newVal;
  },
});
const tabChange = (name) => {
  router.replace({
    name: route.name,
    query: {
      ...route.query,
      [activeTabKey]: name,
    },
  });
};
const handleEdit = (targetName, action) => {
  action === 'add' ? handleAdd() : handleRemove(targetName);
  emit('handleEdit');
};
// 按自然数递增的顺序设置新建标签页的序号，保证数字连贯，采用补位的方式新增
const setNum = (newTabs) => {
  let numList = [];
  // 获取已经新建标签页的序号
  const newTabsNum = newTabs.map((item) => item.num);
  // 生成所有标签页的序号
  for (let i = 0; i < newTabs.length + 1; i++) {
    numList.push(i + 1);
  }
  return numList.find((item) => !newTabsNum.includes(item));
};
const handleAdd = () => {
  const newTabName = Math.random().toString(36).substring(2, 9);
  const newTabs = tabList.value.filter((item) => item.closable);
  const num = setNum(tabList.value, newTabs);
  tabList.value.push({
    label: `新建标签页${num}`,
    num,
    name: newTabName,
    closable: true,
  });
  activeTab.value = newTabName;
  tabChange(newTabName);
};
const handleRemove = (targetName) => {
  ElMessageBox.confirm(`确定要删除 ${targetName} 标签页吗？`, '删除', {
    type: 'warning',
    callback: (action) => {
      if (action === 'confirm') {
        const tabs = tabList.value;
        let activeName = activeTab.value;
        if (activeName === targetName) {
          tabs.forEach((tab, index) => {
            if (tab.name === targetName) {
              const nextTab = tabs[index + 1] || tabs[index - 1];
              if (nextTab) {
                activeName = nextTab.name;
              }
            }
          });
        }
        activeTab.value = activeName;
        tabList.value = tabs.filter((tab) => tab.name !== targetName);
        tabChange(activeName);
      }
    },
  });
};
</script>

<style lang="less" scoped>
.el-tabs {
  box-sizing: border-box;
  overflow-x: hidden;
  display: flex;
  flex: 1;
  flex-direction: column-reverse;
  width: 100%;
  height: 100%;
  padding: 14px;
  --el-tabs-header-height: 30px;
  background-color: var(--el-fill-color-blank);
  border: 1px solid var(--el-border-color-light);
  border-radius: 6px;
  box-shadow: 0 0 12px #0000000d;
}
:deep(.el-tabs__header) {
  margin-bottom: 0;
}
</style>
